"""
项目证书管理系统主程序

用法：
    python main.py <config_file> [选项]

例如：
    python main.py configs/test.json                    # 生成所有证书
    python main.py configs/test.json --root-ca          # 仅生成根 CA
    python main.py configs/test.json --intermediate-ca  # 仅生成中间 CA
    python main.py configs/test.json --server-cert      # 仅生成服务器证书
    python main.py configs/test.json --root-ca --server-cert  # 生成根 CA 和服务器证书

功能：
    1. 加载项目配置文件
    2. 生成根 CA 证书（1个）
    3. 生成中间 CA 证书（多个）
    4. 生成服务器证书（多个）
    5. 所有证书输出到配置文件中指定的 root_path 目录下
    
选项：
    --root-ca          仅生成根 CA 证书
    --intermediate-ca  仅生成中间 CA 证书
    --server-cert      仅生成服务器证书
    如果未指定任何选项，默认生成所有证书
"""
import json
import os
import sys
import argparse
from typing import cast
from config_types import ConfigDict
from make_root_ca import generate_root_ca
from make_intermediate_ca import generate_intermediate_ca
from make_server_cert import generate_server_cert


def load_config(config_path: str) -> ConfigDict:
    """
    加载配置文件
    
    Args:
        config_path: 配置文件路径
    
    Returns:
        配置字典
    """
    if not os.path.exists(config_path):
        raise FileNotFoundError(f"配置文件不存在: {config_path}")
    
    with open(config_path, "r", encoding="utf-8") as f:
        config = cast(ConfigDict, json.load(f))
    
    # 验证必需字段
    if "root_path" not in config:
        raise ValueError("配置文件中缺少 'root_path' 字段")
    
    # 验证可选字段的类型（如果存在）
    if "intermediate_ca" in config and not isinstance(config["intermediate_ca"], list):
        raise ValueError("'intermediate_ca' 必须是列表")
    if "server_cert" in config and not isinstance(config["server_cert"], list):
        raise ValueError("'server_cert' 必须是列表")
    
    return config


def generate_certificate_chain(config: ConfigDict, 
                                generate_root: bool = True,
                                generate_intermediate: bool = True,
                                generate_server: bool = True):
    """
    生成完整的证书链
    
    Args:
        config: 配置字典
        generate_root: 是否生成根 CA
        generate_intermediate: 是否生成中间 CA
        generate_server: 是否生成服务器证书
    """
    # 获取根路径
    root_path = config["root_path"]
    
    print("=" * 60)
    print(f"开始生成 CA 证书链...")
    print(f"根路径: {root_path}")
    print("=" * 60)
    print()
    
    step_count = sum([generate_root, generate_intermediate, generate_server])
    current_step = 0
    
    # 1. 生成根 CA（1个）
    if generate_root:
        if "root_ca" not in config:
            current_step += 1
            print(f"[{current_step}/{step_count}] 跳过根 CA（配置中未定义）\n")
        else:
            current_step += 1
            print(f"[{current_step}/{step_count}] 生成根 CA...")
            root_key_path, root_crt_path = generate_root_ca(config["root_ca"], root_path)
            print(f"✓ 根 CA 私钥: {root_key_path}")
            print(f"✓ 根 CA 证书: {root_crt_path}\n")
    
    # 2. 生成中间 CA（多个）
    if generate_intermediate:
        if "intermediate_ca" not in config:
            current_step += 1
            print(f"[{current_step}/{step_count}] 跳过中间 CA（配置中未定义）\n")
        else:
            intermediate_cas = config["intermediate_ca"]
            if not intermediate_cas:
                current_step += 1
                print(f"[{current_step}/{step_count}] 跳过中间 CA（配置中未定义）\n")
            else:
                current_step += 1
                print(f"[{current_step}/{step_count}] 生成中间 CA（共 {len(intermediate_cas)} 个）...")
                inter_key_paths = []
                inter_crt_paths = []
                for i, inter_config in enumerate(intermediate_cas, 1):
                    print(f"\n  生成第 {i}/{len(intermediate_cas)} 个中间 CA...")
                    inter_key_path, inter_crt_path = generate_intermediate_ca(inter_config, root_path)
                    inter_key_paths.append(inter_key_path)
                    inter_crt_paths.append(inter_crt_path)
                    print(f"  ✓ 中间 CA #{i} 私钥: {inter_key_path}")
                    print(f"  ✓ 中间 CA #{i} 证书: {inter_crt_path}")
                print()
    
    # 3. 生成服务器证书（多个）
    if generate_server:
        if "server_cert" not in config:
            current_step += 1
            print(f"[{current_step}/{step_count}] 跳过服务器证书（配置中未定义）\n")
        else:
            server_certs = config["server_cert"]
            if not server_certs:
                current_step += 1
                print(f"[{current_step}/{step_count}] 跳过服务器证书（配置中未定义）\n")
            else:
                current_step += 1
                print(f"[{current_step}/{step_count}] 生成服务器证书（共 {len(server_certs)} 个）...")
                for i, server_config in enumerate(server_certs, 1):
                    print(f"\n  生成第 {i}/{len(server_certs)} 个服务器证书...")
                    server_key_path, server_crt_path, fullchain_path = generate_server_cert(server_config, root_path)
                    print(f"  ✓ 服务器证书 #{i} 私钥: {server_key_path}")
                    print(f"  ✓ 服务器证书 #{i} 证书: {server_crt_path}")
                    print(f"  ✓ 服务器证书 #{i} 完整链: {fullchain_path}")
                print()
    
    print("=" * 60)
    print(f"证书生成完成！")
    print(f"输出目录: {root_path}")
    print("=" * 60)


def main():
    """主函数"""
    parser = argparse.ArgumentParser(
        description="项目证书管理系统 - 生成完整的证书链",
        formatter_class=argparse.RawDescriptionHelpFormatter,
        epilog="""
示例:
  python main.py configs/test.json
  python main.py configs/production.json
  python main.py configs/test.json --root-ca
  python main.py configs/test.json --intermediate-ca
  python main.py configs/test.json --server-cert
  python main.py configs/test.json --root-ca --server-cert
        """
    )
    parser.add_argument(
        "config_file",
        help="项目配置文件路径（相对于项目根目录或绝对路径）"
    )
    parser.add_argument(
        "--root-ca",
        action="store_true",
        help="仅生成根 CA 证书"
    )
    parser.add_argument(
        "--intermediate-ca",
        action="store_true",
        help="仅生成中间 CA 证书"
    )
    parser.add_argument(
        "--server-cert",
        action="store_true",
        help="仅生成服务器证书"
    )
    
    args = parser.parse_args()
    
    try:
        # 加载配置
        config = load_config(args.config_file)
        
        # 如果指定了任何选项，则只生成指定的证书
        # 如果未指定任何选项，根据配置文件中存在的内容来决定生成什么
        has_any_option = args.root_ca or args.intermediate_ca or args.server_cert
        
        if has_any_option:
            # 用户明确指定了选项
            generate_root = args.root_ca
            generate_intermediate = args.intermediate_ca
            generate_server = args.server_cert
            
            # 验证：如果指定了选项但对应的配置不存在，给出警告
            if generate_root and "root_ca" not in config:
                print(f"警告: 指定了 --root-ca，但配置文件中没有 'root_ca' 配置", file=sys.stderr)
            if generate_intermediate and "intermediate_ca" not in config:
                print(f"警告: 指定了 --intermediate-ca，但配置文件中没有 'intermediate_ca' 配置", file=sys.stderr)
            if generate_server and "server_cert" not in config:
                print(f"警告: 指定了 --server-cert，但配置文件中没有 'server_cert' 配置", file=sys.stderr)
        else:
            # 未指定选项，根据配置文件内容自动决定
            generate_root = "root_ca" in config
            generate_intermediate = "intermediate_ca" in config
            generate_server = "server_cert" in config
        
        # 检查是否有任何需要生成的内容
        if not (generate_root or generate_intermediate or generate_server):
            print("错误: 配置文件中没有可生成的证书类型", file=sys.stderr)
            sys.exit(1)
        
        # 生成证书链
        generate_certificate_chain(
            config,
            generate_root=generate_root,
            generate_intermediate=generate_intermediate,
            generate_server=generate_server
        )
        
    except FileNotFoundError as e:
        print(f"错误: {e}", file=sys.stderr)
        sys.exit(1)
    except ValueError as e:
        print(f"配置错误: {e}", file=sys.stderr)
        sys.exit(1)
    except Exception as e:
        print(f"生成证书时发生错误: {e}", file=sys.stderr)
        import traceback
        traceback.print_exc()
        sys.exit(1)


if __name__ == "__main__":
    main()

